﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TreeView;

namespace TileProcess
{
    public partial class Form1 : Form
    {
        private int _count = 0;
        private string _inputPath;
        private string _inputRoadPath;
        private string _outputPath;
        private int _fromMapZoom;
        private int _toMapZoom;

        private DateTime _startTime;
        private int _lastCount;

        private TaskSchedulerEx _task = new TaskSchedulerEx(4, 4);

        private System.Timers.Timer _timer;

        public Form1()
        {
            InitializeComponent();

            _inputPath = ConfigurationManager.AppSettings["inputPath"];
            _inputRoadPath = ConfigurationManager.AppSettings["inputRoadPath"];
            _outputPath = ConfigurationManager.AppSettings["outputPath"];
            _fromMapZoom = Convert.ToInt32(ConfigurationManager.AppSettings["fromMapZoom"]);
            _toMapZoom = Convert.ToInt32(ConfigurationManager.AppSettings["toMapZoom"]);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            int sleepInterval = 1000;
            int avg = 0;
            _timer = new System.Timers.Timer(sleepInterval);
            _timer.Elapsed += (s, ee) =>
            {
                this.BeginInvoke(new Action(() =>
                {
                    double totalSeconds = DateTime.Now.Subtract(_startTime).TotalSeconds;
                    lblMsg.Text = string.Format("已处理 {0} 张瓦片图", _count);
                    if (_count - _lastCount > 0)
                    {
                        avg = (int)(_count / totalSeconds);
                        lblSpeed.Text = string.Format("当前速度：{0} 张/每秒，平均速度：{1} 张/每秒", (_count - _lastCount) * 1000.0 / sleepInterval, avg);
                    }
                    else
                    {
                        lblSpeed.Text = string.Format("当前速度：{0} 张/每秒，平均速度：{1} 张/每秒", 0, avg);
                        if (_count > 0)
                        {
                            lblMsg.Text += "，处理完成";
                        }
                    }
                    _lastCount = _count;
                }));
            };
            _timer.Interval = sleepInterval;
        }

        private void btnTileProcess_Click(object sender, EventArgs e)
        {
            this.btnTileProcess.Enabled = false;
            _timer.Start();

            Task.Factory.StartNew(() =>
            {
                try
                {
                    Process();
                }
                catch (Exception ex)
                {
                    LogUtil.Error(ex);
                    this.BeginInvoke(new Action(() =>
                    {
                        lblErrorMsg.Text = "出错：" + ex.Message + "\r\n" + ex.StackTrace;
                    }));
                }
            }, TaskCreationOptions.LongRunning);
        }

        /// <summary>
        /// 瓦片纠偏处理
        /// </summary>
        private void Process()
        {
            _startTime = DateTime.Now;
            Regex regex = new Regex(@"\\(\d+)\\(\d+)\\tile.png", RegexOptions.IgnoreCase);
            for (int i = _fromMapZoom; i <= _toMapZoom; i++)
            {
                if (!Directory.Exists(_inputPath + "\\" + i)) continue;
                string[] fileArr = Directory.GetFiles(_inputPath + "\\" + i, "*.*", SearchOption.AllDirectories);
                foreach (string file in fileArr)
                {
                    ThreadData data = new ThreadData();
                    data.File = file;
                    data.I = i;

                    _task.Run((obj) =>
                    {
                        ThreadData d = obj as ThreadData;

                        Match match = regex.Match(d.File);
                        if (match.Success)
                        {
                            int x = Convert.ToInt32(match.Groups[1].Value);
                            int y = Convert.ToInt32(match.Groups[2].Value);

                            string filePath1 = string.Format(@"{0}\{1}\{2}\{3}\tile.png", _inputPath, d.I, x, y);
                            string filePath2 = string.Format(@"{0}\{1}\{2}\{3}\tile.png", _inputRoadPath, d.I, x, y);
                            string targetPath = string.Format(@"{0}\{1}\{2}\{3}.png", _outputPath, d.I, x, y);

                            if (!File.Exists(targetPath) && File.Exists(filePath1) && File.Exists(filePath2))
                            {
                                Bitmap bmpNew = new Bitmap(256, 256, PixelFormat.Format32bppArgb);
                                bmpNew.SetResolution(96, 96);
                                Graphics graph = Graphics.FromImage(bmpNew);

                                DrawImage(filePath1, graph);
                                DrawImage(filePath2, graph);

                                string dirPath = Path.GetDirectoryName(targetPath);
                                if (!Directory.Exists(dirPath))
                                {
                                    Directory.CreateDirectory(dirPath);
                                }
                                bmpNew.Save(targetPath);

                                bmpNew.Dispose();
                                bmpNew = null;
                                graph.Dispose();
                                graph = null;
                            }

                            Interlocked.Increment(ref _count);
                        }
                    }, data);
                }
            }
        }

        private void DrawImage(string filePath, Graphics graph)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            byte[] bArr = new byte[fs.Length];
            int readCount = fs.Read(bArr, 0, bArr.Length);
            MemoryStream ms = new MemoryStream(bArr, 0, readCount);
            Bitmap bmpSource = new Bitmap(ms);
            bmpSource.SetResolution(96, 96);
            graph.DrawImage(bmpSource, 0, 0, new RectangleF(0, 0, 256, 256), GraphicsUnit.Pixel);
            graph.Flush();

            fs.Close();
            ms.Close();
            bmpSource.Dispose();
        }

    }
}
